﻿Shader "Unlit/UnlitSkinMesh"
{
    Properties
    {
        _BaseMap ("Example Texture", 2D) = "white" {}
        _BaseColor ("Example Colour", Color) = (0, 0.66, 0.73, 1)
        _AnimTex ("AnimTex", 2D) = "white" {}
        _GroundHeight ("Ground Height", Float) = 0
        _ShadowColor ("Shadow Color", Color) = (0, 0, 0, 0.3)
    }
    SubShader
    {
        Tags
        {
            "RenderPipeline" = "UniversalPipeline"
            "RenderType" = "Opaque"
            "Queue" = "Geometry+300"
        }

        HLSLINCLUDE
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        #include "GPUInstancingSkinningMesh.hlsl"

        CBUFFER_START(UnityPerMaterial)
        float4 _BaseMap_ST;
        float4 _BaseColor;
        float4 _GroundHeight;
        float4 _ShadowColor;
        CBUFFER_END
        ENDHLSL

        Pass
        {
            Name "Unlit"
            Tags
            {
                "LightMode" = "UniversalForward"
            }

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 4.5

            struct a2v
            {
                float4 posOS : POSITION;
                float2 uv : TEXCOORD0;
                float4 uv1 : TEXCOORD1;
                float4 uv2 : TEXCOORD2;
                float3 normalOS : NORMAL;
                float4 color : COLOR;
                uint instanceID : SV_InstanceId; // instanceID 实例在缓冲中的索引
            };

            struct v2f
            {
                float4 posCS : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 normalWS : TEXCOORD1;
                float4 color : COLOR;
            };

            TEXTURE2D(_BaseMap);
            SAMPLER(sampler_BaseMap);

            v2f vert(a2v v)
            {
                v2f o;
                
                float4x4 trans = transBuf[v.instanceID];
                AnimData animData = animDataBuf[v.instanceID];
                int frameIndex = animData.playingIndex;
                
                float4 pos = GetAnimPosition(trans, v.posOS, frameIndex, v.uv1, v.uv2);
                float4 normal = GetAnimPosition(trans, float4(v.normalOS, 0), frameIndex, v.uv1, v.uv2);
                
                // 测试代码，不包含 SkinningMesh
                // float4 pos = mul(trans, v.posOS);
                // float4 normal = mul(trans, float4(v.normalOS, 0));
                
                o.posCS = TransformObjectToHClip(pos);
                o.normalWS = TransformObjectToWorld(normal);
                o.uv = v.uv;
                o.color = v.color;
                
                return o;
            }

            float4 frag(v2f i) : SV_Target
            {
                float4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv);
                return baseMap * _BaseColor * i.color;
            }
            ENDHLSL
        }
        
        Pass
        {
            Name "PlanarShadow"
            
            // 引入模板用来解决模型拍扁后重叠区域的颜色叠加问题
            Stencil
            {
                Ref 0
                Comp equal
                Pass incrWrap
                Fail keep
                ZFail keep
            }
            
            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite off
            Cull Off
            Offset -1, 0

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 4.5

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            struct Attributes
            {
                float4 posOS : POSITION;
                float4 uv1 : TEXCOORD1;
                float4 uv2 : TEXCOORD2;
                uint instanceID : SV_InstanceId; // instanceID 实例在缓冲中的索引
            };

            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float4 color : COLOR;
            };

            TEXTURE2D(_BaseMap);
            SAMPLER(sampler_BaseMap);

            // 将模型空间的顶点转换到平面阴影的世界坐标
            float3 ShadowProjectPos(float4 vertPos)
            {
                float3 shadowPos;

                float3 worldPos = TransformObjectToWorld(vertPos.xyz);

                Light mainLight = GetMainLight();
                float3 lightDir = normalize(mainLight.direction);

                //地平线高度
                float groundHeight = _GroundHeight;
                shadowPos.y = min(worldPos.y, groundHeight);
                shadowPos.xz = worldPos.xz - lightDir.xz * max(0, worldPos.y - groundHeight) / lightDir.y;

                return shadowPos;
            }
            
            Varyings vert(Attributes input)
            {
                Varyings output;

                float4x4 trans = transBuf[input.instanceID];
                AnimData animData = animDataBuf[input.instanceID];
                int frameIndex = animData.playingIndex;
                float4 pos = GetAnimPosition(trans, input.posOS, frameIndex, input.uv1, input.uv2);
                
                float3 shadowPos = ShadowProjectPos(pos);
                output.positionCS = TransformWorldToHClip(shadowPos);
                output.color = _ShadowColor;
                return output;
            }

            float4 frag(Varyings input) : SV_Target
            {
                return input.color;
            }
            ENDHLSL
        }
    }
}
